// 为防止环形队列的index出现溢出，应该在index到最大值的时候进行reindex
struct cycle {

	uint8_t read;
	uint8_t write;
	int arr[16];
	int max = 127;
	int length = 8;
	void re_indx(){
		read = read % length;
		write = write % length;
		//write是不可能小于read的，出现这种情况只能是write写完n圈后又开始， 而read还在n- 1圈的某个位置
		if (write < read ) {
			write = write + length;
		}

	}
};







struct  BuffUnit {
    long  long vol;
    int ask;
    long long  asize;
    int bid;
    long long  bsize;
    int idx = 0;

    BuffUnit(){
        vol = 0;
        ask = 0;
        asize = 0;
        bid = 0;
        bsize = 0;
        idx = 0;
    }
    void reset(){
        vol = 0;
        ask = 0;
        asize = 0;
        bid = 0;
        bsize = 0;

    }
    BuffUnit(const BuffUnit & unit){
        vol = unit.vol;
        ask = unit.ask;
        asize = unit.asize;
        bid = unit.bid;
        bsize = unit.bsize;
        idx = unit.idx;
    }

    BuffUnit &operator=(const BuffUnit & unit){
        vol = unit.vol;
        ask = unit.ask;
        asize = unit.asize;
        bid = unit.bid;
        bsize = unit.bsize;
        idx = unit.idx;
        return *this;
    }

};

unsigned  int max_widx = 0;
unsigned  int max_ridx = 0;

template <typename T >
struct identity{
    typedef T  type;
};

template<typename T>
class VectorSized{

public:
    template<typename N>
    void fills(){
        fill_detail( identity<N>());
    }

    template<typename  N>
    void fill_detail( identity<N>){
    }

    void fill_detail( identity<int>){
        fill(data.begin(), data.end(), 0);
    }

    void fill_detail( identity<double>){
        fill(data.begin(), data.end(), 0);
    }

    void fill_detail (identity<BuffUnit>){
        BuffUnit zero;
        memset(&zero, 0 , sizeof(zero) );
        fill(data.begin(), data.end(),zero );
    }


    string ticker;
    vector<T> data;
//private:
    size_t write_idx;
    size_t read_idx;
    int size;
public:
    VectorSized(const int &p_size = 0){
        write_idx = 0;
        read_idx = 0;
        size = p_size == 0 ? VECTOR_SIZED : p_size;
        data.resize(size);
        //  fun<T>();
        //fills(data.begin(), data.end(), 0);
        fills<T>();
    }


    void push(const T & t ){
        if(write_idx < size){
            data[write_idx++] = t;
        }
        else{
            realloc();
            data[write_idx++] = t;
        }
    }
    size_t get_write_idx(){
        return write_idx;
    }
    void realloc() {

        vector<T> temp;
        temp.resize(size);
        for(int i =0 ;i < size; i++){
            temp[i] =data[i];
        }

        data.resize(2 * size);

        for(int j = 0; j < size; j++ ){
            data[j] = temp[j];
        }
        size = 2 * size;
    }
};

class CycleVector{
//private:
public:
    vector<BuffUnit> buf_vec;
    size_t read_idx; //size_t  enough for a ticker
    size_t write_idx;
    size_t pre_read;

    long long vol_925;
    unsigned size;
public:
    string ticker;
    int pre_vol;
    CycleVector(const int &p_size = 0){
        read_idx = 0;
        write_idx = 0;
        pre_read = 0;
        vol_925 = 0;
        pre_vol = 0;
        size = p_size == 0 ? UPDATE_SIZE : p_size;
        buf_vec.resize(size);
    }
    //数据溢出情况要怎么处理  即write_idx 不能++了， 但是仍然要推数据，对vector扩容
    void push(const BuffUnit & line ){
        if (write_idx - read_idx < size ) {

            buf_vec[mod(write_idx)] = line;
            write_idx++;
        }
        else{
            cout<<"buffer overflow , need  realloc " <<ticker <<"[widx]" <<write_idx << "[read_idx]" << read_idx  <<endl;
            realloc();
            buf_vec[mod(write_idx)] = line;
            write_idx++;
        }
        max_widx = write_idx > max_widx ? write_idx : max_widx;
    }
    // realloc时 元素的移动顺序为 readidx -> size 和  0 ->readidx-1     ,再置writeidx = size, readidx = 0,
    void realloc() {
        vector<BuffUnit> temp;
        temp.resize(buf_vec.size());
        //先将 readidx -> size-1的值移动到 temp 中
        size_t idx = 0;
#ifdef  WHERE_SEG
        cout<<  "[realloc  pos 1]" <<
            "[read]" << read_idx <<
            "[write_idx]"<< write_idx <<endl;
#endif

        for (size_t j = read_idx; j < buf_vec.size(); idx++, j++) {
            temp[idx] = buf_vec[j];
        }
#ifdef  WHERE_SEG
        cout<<  "[realloc pos 2]" <<
            "[read]" << read_idx <<
            "[write_idx]"<< write_idx <<endl;
#endif

        // 再将0 ->readidx-1的值移到 temp中      idx<temp.size() 是需要的
        for (size_t k = 0; k < read_idx && idx<temp.size(); k++) {
            temp[idx++] = buf_vec[k];
        }

        buf_vec.resize(buf_vec.size() * 2);

#ifdef  WHERE_SEG
        cout<<  "[realloc pos 3]" <<
            "[read]" << read_idx <<
            "[write_idx]"<< write_idx <<endl;
#endif
        for (size_t i = 0; i < temp.size(); i++) {
            buf_vec[i] = temp[i];
        }
        read_idx = 0;
        write_idx = size;
        size = size * 2;

#ifdef  WHERE_SEG
        cout<<  "[after realloc]" <<
                "[read]" << read_idx <<
                "[write_idx]"<< write_idx <<endl;
#endif
    }
    // 注意read_idx 类型的一致 否则容易出现segment fault
    inline  int mod(size_t x) noexcept{
        return x % size;
    }



    /// -1 r==w ,  0 match vol ,   1 cant match vol, return left value ,  2 cant match vol, return right value
    const int get_max_vol(){
        return buf_vec[ mod(write_idx -1)].vol;
    }
    const  BuffUnit  back(){
        return buf_vec[ mod(write_idx -1)];
    }
    pair<BuffUnit, int>  find(const int& vol,const int pos = 0 , const int cnt = 0, const int is_second=0){
#ifdef  WHERE_SEG
        cout<<  "[curr find vol]" << vol <<
                "[read]" << read_idx <<
                "[write_idx]"<< write_idx <<
                "[ticker_in_cycle]"<< ticker <<
                "[max_vol]" << buf_vec[ mod(write_idx -1)].vol  <<endl;
    #endif
        BuffUnit ex;
        ex.vol = -1;
        pre_read = read_idx;
        for(;;){
#ifdef  WHERE_SEG
            if (ticker == "159885"){
                cout<<  "[special read]" <<read_idx <<
                        "[write_idx]"<<write_idx<<
                        "[pos]"<<pos<<
                        "[cnt]"<<cnt<<
                        "[is_seconds]" <<is_second<<
                        "[vol]"<<vol<<
                        "[size]"<<size<<
                        "[buf_vec.size]" << buf_vec.size()<< endl;
             //  int cnt = 0;
             //  for(int i= read_idx; cnt<10 && i < buf_vec.size(); i++){
             //          std::cout<<"[buf_vec value]"<< buf_vec[ mod(i)].vol <<"[i]" << i  <<endl;
             //          cnt++;
             //  }
            }
#endif

            if(read_idx == write_idx )  return {ex,-1};
            //int  curr = buf_vec[read_idx++%size].vol;


            int  curr = buf_vec[ mod(read_idx) ].vol;
            if (curr < vol) {
                read_idx++;
                max_ridx = read_idx > max_ridx ? read_idx : max_ridx;
                continue;
            }
            if (curr == vol ) {
                read_idx++;
#ifdef WHERE_SEG
                buf_vec[mod(read_idx-1)].idx = mod(read_idx -1);
#endif
                return {buf_vec[mod(read_idx-1)], 0};
            }
            //即read_idx 已经移到了比snap成交量大的情况，这种情况的处理方式
            if( curr > vol){
                int l_diff = vol - buf_vec[ mod(read_idx - 1) ].vol;
                int r_diff = curr - vol;
                size_t curr_read = read_idx;
                ////可能会超前，然后一直错位,这里考虑--
                read_idx = read_idx--  > 0 ? read_idx : 0;
                if (l_diff < r_diff){

#ifdef WHERE_SEG
                    buf_vec[mod(curr_read-1)].idx = mod(curr_read -1);
#endif
                    return {buf_vec[ mod(curr_read - 1) ], 1};

                }
                else{

#ifdef WHERE_SEG
                    buf_vec[mod(curr_read)].idx = mod(curr_read) ;
#endif
                    return {buf_vec[ mod(curr_read )],2};


                }
            }
        }
    }
};

